﻿using System;
using System.Collections.Generic;
using System.Text;
using HAVNet.Intros.AST;


namespace HAVNet.Transformers.Walkers
{
    delegate void StmtWalkerFunction (ASTStatement stmt, int prof);

    class WalkerStmts
    {
        public static void get (ASTBlock block, StmtWalkerFunction f, int depth)
        { 
            //
        }

        public static void get (ASTStatement stmt, StmtWalkerFunction f, int depth)
        {
            stmtWalk (stmt, f, depth);
        }

        static void stmtWalk (ASTStatement stmt, StmtWalkerFunction f, int depth)
        {
            if (stmt is ASTEmbStmtBlock)
            {
                f(stmt, depth);
                
                foreach (ASTStatement stmtX in ((ASTEmbStmtBlock)stmt).block.stmts)
                    stmtWalk (stmtX, f, depth + 1);
            }
            else if (stmt is ASTEmbStmtBreak)
            {
                f(stmt, depth);
            }
            else if (stmt is ASTEmbStmtChecked)
            {
                f(stmt, depth);

                foreach (ASTStatement stmtX in ((ASTEmbStmtChecked)stmt).block.stmts)
                    stmtWalk (stmtX, f, depth + 1);
            }
            else if (stmt is ASTEmbStmtContinue)
            {
                f(stmt, depth);
            }
            else if (stmt is ASTEmbStmtDo)
            {
                f(stmt, depth);

                stmtWalk(((ASTEmbStmtDo)stmt).statement, f, depth + 1);
            }
            else if (stmt is ASTEmbStmtFixed)
            {
                f(stmt, depth);

                stmtWalk(((ASTEmbStmtFixed)stmt).statement, f, depth + 1);
            }
            else if (stmt is ASTEmbStmtFor)
            {
                f(stmt, depth);

                stmtWalk(((ASTEmbStmtFor)stmt).statement, f, depth + 1);
            }
            else if (stmt is ASTEmbStmtForeach)
            {
                f(stmt, depth);

                stmtWalk(((ASTEmbStmtForeach)stmt).statement, f, depth + 1);
            }
            else if (stmt is ASTEmbStmtGoto)
            {
                f(stmt, depth);
            }
            else if (stmt is ASTEmbStmtIf)
            {
                f(stmt, depth);

                stmtWalk(((ASTEmbStmtIf)stmt).thenStatement, f, depth + 1);
                stmtWalk(((ASTEmbStmtIf)stmt).elseStatement, f, depth + 1);
            }
            else if (stmt is ASTEmbStmtLock)
            {
                f(stmt, depth);

                stmtWalk(((ASTEmbStmtLock)stmt).statement, f, depth + 1);
            }
            else if (stmt is ASTEmbStmtReturn)
            {
                f(stmt, depth);
            }
            else if (stmt is ASTEmbStmtSemicolon)
            {
                f(stmt, depth);
            }
            else if (stmt is ASTEmbStmtStatementExpression)
            {
                f(stmt, depth);
            }
            else if (stmt is ASTEmbStmtSwitch)
            {
                f(stmt, depth);

                foreach (ASTSwitchSection switchSection in ((ASTEmbStmtSwitch)stmt).switchSections)
                    foreach (ASTStatement stmtX in switchSection.statements)
                        stmtWalk(stmtX, f, depth + 1);
            }
            else if (stmt is ASTEmbStmtThrow)
            {
                f(stmt, depth);
            }
            else if (stmt is ASTEmbStmtTry)
            {
                f(stmt, depth);

                foreach (ASTStatement stmtX in ((ASTEmbStmtTry)stmt).tryBlock.stmts)
                    stmtWalk(stmtX, f, depth + 1);

                foreach (ASTCatch @catch in ((ASTEmbStmtTry)stmt).catchs)
                    foreach (ASTStatement stmtX in @catch.block.stmts)
                        stmtWalk(stmtX, f, depth + 1);

                if (((ASTEmbStmtTry)stmt).finallyBlock != null)
                    foreach (ASTStatement stmtX in ((ASTEmbStmtTry)stmt).finallyBlock.stmts)
                        stmtWalk(stmtX, f, depth + 1);
            }
            else if (stmt is ASTEmbStmtUnchecked)
            {
                f(stmt, depth);

                foreach (ASTStatement stmtX in ((ASTEmbStmtUnchecked)stmt).block.stmts)
                    stmtWalk(stmtX, f, depth + 1);
            }
            else if (stmt is ASTEmbStmtUnsafe)
            {
                f(stmt, depth);

                foreach (ASTStatement stmtX in ((ASTEmbStmtUnsafe)stmt).block.stmts)
                    stmtWalk(stmtX, f, depth + 1);
            }
            else if (stmt is ASTEmbStmtUsing)
            {
                f(stmt, depth);

                stmtWalk(((ASTEmbStmtUsing)stmt).statement, f, depth + 1);
            }
            else if (stmt is ASTEmbStmtWhile)
            {
                f(stmt, depth);

                stmtWalk(((ASTEmbStmtWhile)stmt).statement, f, depth + 1);
            }
            else if (stmt is ASTEmbStmtYield)
            {
                f(stmt, depth);
            }
        }
    }
}
